package com.engine.salary.service.impl;

import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.biz.AttendQuoteBiz;
import com.engine.salary.biz.AttendQuoteDataBiz;
import com.engine.salary.biz.AttendQuoteDataValueBiz;
import com.engine.salary.config.SalaryElogConfig;
import com.engine.salary.entity.datacollection.dto.AttendQuoteListDTO;
import com.engine.salary.entity.datacollection.param.AttendQuoteQueryParam;
import com.engine.salary.entity.datacollection.po.AttendQuotePO;
import com.engine.salary.entity.salaryacct.po.SalaryAcctRecordPO;
import com.engine.salary.enums.auth.AuthFilterTypeEnum;
import com.engine.salary.enums.salaryaccounting.SalaryAcctRecordStatusEnum;
import com.engine.salary.exception.SalaryRunTimeException;
import com.engine.salary.mapper.datacollection.AttendQuoteMapper;
import com.engine.salary.service.AttendQuoteService;
import com.engine.salary.service.SalaryAcctRecordService;
import com.engine.salary.service.SalarySobService;
import com.engine.salary.service.TaxAgentService;
import com.engine.salary.service.auth.AuthService;
import com.engine.salary.service.auth.AuthServiceImpl;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.SalaryLoggerUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.engine.salary.util.page.PageInfo;
import com.engine.salary.util.page.SalaryPageUtil;
import org.apache.commons.collections4.CollectionUtils;
import weaver.hrm.User;

import java.time.LocalDate;
import java.time.YearMonth;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

public class AttendQuoteServiceImpl extends Service implements AttendQuoteService {

    private AttendQuoteBiz biz = new AttendQuoteBiz();
    private AttendQuoteDataBiz dataBiz = new AttendQuoteDataBiz();
    private AttendQuoteDataValueBiz dataValueBiz = new AttendQuoteDataValueBiz();

    private AttendQuoteMapper getAttendQuoteMapper() {
        return MapperProxyFactory.getProxy(AttendQuoteMapper.class);
    }

    private SalaryAcctRecordService getSalaryAcctRecordService(User user) {
        return ServiceUtil.getService(SalaryAcctRecordServiceImpl.class, user);
    }

    private SalarySobService getSalarySobService(User user) {
        return ServiceUtil.getService(SalarySobServiceImpl.class, user);
    }

    private TaxAgentService getTaxAgentService(User user) {
        return ServiceUtil.getService(TaxAgentServiceImpl.class, user);
    }
    public AuthService getAuthService(User user) {
        return ServiceUtil.getService(AuthServiceImpl.class, user);
    }

    @Override
    public PageInfo<AttendQuoteListDTO> listPage(AttendQuoteQueryParam queryParam) {

        List<String> declareMonth = queryParam.getSalaryYearMonth();
        if (CollectionUtils.isNotEmpty(declareMonth)) {
            queryParam.setSalaryYearMonth(declareMonth.stream().map(e -> e + "-01 00:00:00").collect(Collectors.toList()));
            queryParam.setSalaryYearMonthDate(declareMonth.stream().map(e -> e + "-01 00:00:00").map(SalaryDateUtil::dateStrToLocalTime).collect(Collectors.toList()));
        }

        List<AttendQuoteListDTO> list = getAttendQuoteMapper().list(queryParam);
        list = getAuthService(user).auth(list, AuthFilterTypeEnum.DATA_OPT, AttendQuoteListDTO.class);

        return SalaryPageUtil.buildPage(queryParam.getCurrent(), queryParam.getPageSize(),
                list, AttendQuoteListDTO.class);
    }

    @Override
    public String delete(Collection<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            throw new SalaryRunTimeException("参数错误");
        }
        List<AttendQuoteListDTO> attendQuotes = biz.list(AttendQuoteQueryParam.builder().ids(ids).build());
        attendQuotes = getAuthService(user).auth(attendQuotes, AuthFilterTypeEnum.ADMIN_DATA, AttendQuoteListDTO.class);
        if (CollectionUtils.isEmpty(attendQuotes)) {
            throw new SalaryRunTimeException("无权限删除数据！");
        }

        List<AttendQuoteListDTO> accountingAttendQuotes = attendQuotes.stream().filter(e -> e.getSalaryAccountingStatus().equals(1)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(accountingAttendQuotes)) {
            throw new SalaryRunTimeException("已经核算完成的数据不能删除");
        }

        List<SalaryAcctRecordPO> salaryAcctRecordPOS = getSalaryAcctRecordService(user).listSome(SalaryAcctRecordPO.builder().salarySobId(attendQuotes.get(0).getSalarySobId())
                .salaryMonth(attendQuotes.get(0).getSalaryYearMonth()).build());
        Optional<SalaryAcctRecordPO> haveArchived = salaryAcctRecordPOS.stream().filter(PO -> PO.getStatus() > SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue()).findFirst();
        if(haveArchived.isPresent()){
            throw new SalaryRunTimeException("已经核算完成的数据不能删除");
        }
        List<Long> unAccountingIds = attendQuotes.stream().filter(e -> e.getSalaryAccountingStatus().equals(0)).map(AttendQuoteListDTO::getId).collect(Collectors.toList());
        // 1.删除未核算的考勤引用
        biz.deleteByIds(unAccountingIds);

        // List<AttendQuoteDataPO> attendQuoteDatas = dataBiz.listSome(AttendQuoteDataQueryParam.builder().unAccountingIds(unAccountingIds).build());
        // 2.删除考核引用对应的考核数据
        dataBiz.deleteByAttendQuoteIds(unAccountingIds);

        // 3.删除考核数据对应的考核值
        dataValueBiz.deleteByAttendQuoteIds(unAccountingIds);
        // List<Long> attendQuoteDataIds = attendQuoteDatas.stream().map(AttendQuoteDataPO::getId).collect(Collectors.toList());
        // if (CollectionUtils.isNotEmpty(attendQuoteDataIds)) {
        //     dataValueBiz.deleteByAttendQuoteDataIds(attendQuoteDataIds);
        // }

        // 记录日志
       attendQuotes.forEach(e -> {
           SalaryLoggerUtil.recordDeleteSingleLog(SalaryElogConfig.attendQuoteLoggerTemplate,
                   e.getId(),
                   SalaryI18nUtil.getI18nLabel(0, SalaryDateUtil.getFormatYearMonth(e.getSalaryYearMonth()) + " " + e.getSalarySobName()),
                   SalaryI18nUtil.getI18nLabel(0, "删除考勤引用"),
                   SalaryI18nUtil.getI18nLabel(0, "删除考勤引用") +
                           "：[" + SalaryI18nUtil.getI18nLabel(0, "薪资所属月") + "：" + e.getSalaryYearMonth() + "，" +
                           SalaryI18nUtil.getI18nLabel(0, "关联账套") + "：" + e.getSalarySobName() + "]",
                   e,
                   user);
       });

        return null;
    }


    @Override
    public Boolean checkOperation(YearMonth salaryYearMonth, List<Long> salarySobIds) {
        // 已经核算过的不可操作
        List<SalaryAcctRecordPO> salaryAcctRecords = getSalaryAcctRecordService(user).listBySalarySobIds(salarySobIds);
        AtomicReference<Boolean> isEnableOperation = new AtomicReference<>(Boolean.TRUE);
        salaryAcctRecords.forEach(e -> {
            boolean isAccounted = e.getSalaryMonth().equals(SalaryDateUtil.localDateToDate(LocalDate.of(salaryYearMonth.getYear(), salaryYearMonth.getMonth(), 1)))
                    && e.getStatus() > SalaryAcctRecordStatusEnum.NOT_ARCHIVED.getValue();
            if (isAccounted) {
                isEnableOperation.set(Boolean.FALSE);
            }
        });
        return isEnableOperation.get();
    }

    @Override
    public AttendQuotePO getById(Long id) {
        if (id == null) {
            return null;
        }
        return getAttendQuoteMapper().getById(id);
    }
}
